unit uSBD_ServiceProvider;
interface
uses Classes, Generics.Collections;

const
  CSI = '\';   // Config string Control Sequence Introducer. Control Sequences are \\ or \,
  Sep = ',';   // Config string list item seperator.
  sClientRef = 'client'; // Use: decorate an IInterface data member/property with [Injection('client')]

type
IServiceProvider = interface;
TServiceFactory = reference to function( Obj: TObject; const Config: string;
  const ServiceProvider: IServiceProvider): IInterface;

IServiceProvider = interface
  ['{1C46BAEA-B723-4E07-B1A1-1F1E286AC421}']
    function  RegisterLiveService   ( const ServiceIID: TGUID; const Service: IInterface; const Config: string = ''): integer;
    function  RegisterFlyweightService( const ServiceIID: TGUID; CreateBase: TClass; Factory: TServiceFactory; const Config: string = ''): integer;
    function  RegisterServiceClass( Registrant: TClass; const ServiceIID: TGUID): TList<integer>;
    procedure DeregisterService( RegistrationCookie: integer);
    function  Acquire( const Client: IInterface; const ServiceIID: TGUID; out Intf; const Config: string = ''): boolean;
    procedure ShutDown;
  end;

TSBDUnit_BaseAttribute = class( TCustomAttribute) end;

Injection = class( TSBDUnit_BaseAttribute)
  public
    FConfig: string;

    constructor Create;                           overload;
    constructor Create( const Config1: string);   overload;
  end;

Configuration = class( TSBDUnit_BaseAttribute)
   public
     FConfigs: TStrings;
     FMaxPoolSize: integer; // 0 for unlimited.

     constructor Create;                             overload;
     constructor Create( const Config1: string);     overload;
     destructor Destroy; override;
   end;

BlacklistConfigs = class( TSBDUnit_BaseAttribute)
   public
     FConfigs: TStrings;

     constructor Create( const Config1: string);     overload;
     destructor Destroy; override;
   end;


implementation





uses SysUtils;
{ Configuration }

constructor Configuration.Create;
begin
FConfigs := TStringList.Create;
FConfigs.Add('');
FMaxPoolSize := 0// 0 for unlimited.
end;

function CommaSplit( const CommaSeparedList: string): TStrings;
var
  Left, Right: string;
  p, q: integer;
  FoundSep: boolean;
begin
 // Comma separated string.
 // Escape sequence:  \,  ==>  ,
 // Escape sequence:  \\  ==>  \
result := TStringList.Create;
Right := CommaSeparedList;
repeat
  Left := '';
  FoundSep := False;
  while (Right <> '') and (not FoundSep) do
    begin
    p := Pos( Sep, Right);
    q := Pos( CSI, Right);
    if (p = 0) or ((q <> 0) and (q < p)) then
      p := q;
    if p > 0 then
        begin
        if Right[p] = Sep then
            begin
            Left  := Left + Copy( Right, 1, p-1);
            Delete( Right, 1, p);
            FoundSep := True;
            end
          else if (p < Length(Right)) and ((Right[p+1]=Sep) or (Right[p+1]=CSI)) then
            begin
            Left  := Left + Copy( Right, 1, p-1) + Right[p+1];
            Delete( Right, 1, p+1)
            end
          else
            begin
            Left  := Left + Copy( Right, 1, p);
            Delete( Right, 1, p)
            end
        end
      else
        begin
        Left  := Left + Right;
        Right := '';
        FoundSep := True;
        end
    end;
  if (Left <> '') and (result.IndexOf( Left) = -1) then
    result.Add( Left)
until Right = '';
if result.Count = 0 then
  result.Add( '')
end;


constructor Configuration.Create( const Config1: string);
begin
FConfigs := CommaSplit( Config1);
FMaxPoolSize := 0// 0 for unlimited.
end;


destructor Configuration.Destroy;
begin
FConfigs.Free;
inherited
end;


{ Injection }

constructor Injection.Create;
begin
FConfig := ''
end;

constructor Injection.Create( const Config1: string);
begin
FConfig := Config1
end;

{ BlacklistConfigs }

constructor BlacklistConfigs.Create( const Config1: string);
var
  Dummy: integer;
begin
FConfigs := CommaSplit( Config1)
end;

destructor BlacklistConfigs.Destroy;
begin
FConfigs.Free;
inherited
end;

end.
